#pragma once  // 防止头文件重复包含

// 必要的头文件包含
#include <iostream>     // 标准输入输出
#include <string>       // 字符串类
#include <strings.h>    // bzero等字符串操作
#include <cstring>      // C风格字符串操作
#include <sys/types.h>  // 基本系统数据类型
#include <sys/socket.h> // 套接字接口
#include <netinet/in.h> // Internet地址族
#include <arpa/inet.h>  // IP地址转换函数
#include <functional>   // std::function
#include "Log.hpp"      // 日志类

// 定义回调函数类型：接收一个string参数，返回一个string
// using func_t = std::function<std::string(const std::string&)>;
typedef std::function<std::string(const std::string&)> func_t;

Log lg;  // 全局日志对象

// 错误码枚举
enum{
    SOCKET_ERR=1,  // 套接字创建错误
    BIND_ERR       // 绑定错误
};

// 默认配置
uint16_t defaultport = 8080;              // 默认端口号
std::string defaultip = "0.0.0.0";        // 默认IP地址（监听所有网卡）
const int size = 1024;                    // 缓冲区大小

class UdpServer{
public:
    // 构造函数：初始化服务器参数
    UdpServer(const uint16_t &port = defaultport, const std::string &ip = defaultip)
        :sockfd_(0), port_(port), ip_(ip), isrunning_(false)
    {}

    // 初始化服务器
    void Init()
    {
        // 1. 创建UDP套接字
        sockfd_ = socket(AF_INET, SOCK_DGRAM, 0); // AF_INET: IPv4协议族, SOCK_DGRAM: UDP数据报套接字
        if(sockfd_ < 0)
        {
            lg(Fatal, "socket create error, sockfd: %d", sockfd_);
            exit(SOCKET_ERR);
        }
        lg(Info, "socket create success, sockfd: %d", sockfd_);

        // 2. 绑定套接字到指定地址和端口
        struct sockaddr_in local;                    // 本地地址结构
        bzero(&local, sizeof(local));               // 清零地址结构
        local.sin_family = AF_INET;                 // 使用IPv4地址族
        local.sin_port = htons(port_);              // 将端口号转换为网络字节序
        local.sin_addr.s_addr = inet_addr(ip_.c_str()); // 将IP地址转换为网络字节序
        // local.sin_addr.s_addr = htonl(INADDR_ANY);   // 替代方案：监听所有网卡

        // 绑定套接字
        if(bind(sockfd_, (const struct sockaddr *)&local, sizeof(local)) < 0)
        {
            lg(Fatal, "bind error, errno: %d, err string: %s", errno, strerror(errno));
            exit(BIND_ERR);
        }
        lg(Info, "bind success, errno: %d, err string: %s", errno, strerror(errno));
    }

    // 运行服务器主循环
    void Run(func_t func) // 使用回调函数处理请求
    {
        isrunning_ = true;
        char inbuffer[size];  // 接收数据的缓冲区

        while(isrunning_)
        {
            struct sockaddr_in client;         // 客户端地址结构
            socklen_t len = sizeof(client);    // 地址结构长度

            // 接收数据
            ssize_t n = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, 
                                (struct sockaddr*)&client, &len);
            if(n < 0)
            {
                lg(Warning, "recvfrom error, errno: %d, err string: %s", 
                   errno, strerror(errno));
                continue;
            }
            inbuffer[n] = 0;  // 字符串结束符

            // 处理请求并发送响应
            std::string info = inbuffer;
            std::string echo_string = func(info);  // 调用回调函数处理请求
            sendto(sockfd_, echo_string.c_str(), echo_string.size(), 0, 
                   (const sockaddr*)&client, len); // 发送响应
        }
    }

    // 析构函数：清理资源
    ~UdpServer()
    {
        if(sockfd_ > 0) close(sockfd_);
    }

private:
    int sockfd_;     // 网络套接字文件描述符
    std::string ip_; // 服务器IP地址
    uint16_t port_;  // 服务器端口号
    bool isrunning_; // 服务器运行状态标志
};